package cn.maihe.elg.operation.centers.epoint.channel;

import cn.maihe.elg.operation.centers.epoint.channel.service.*;
import cn.maihe.elg.operation.centers.epoint.dto.EpointBaseRespDTO;
import cn.maihe.elg.operation.centers.epoint.dto.channel.*;
import cn.maihe.elg.operation.centers.epoint.enums.EpointRespCodeEnum;
import cn.maihe.elg.operation.centers.epoint.dto.channel.EpointBaohanNoticeReqDTO;
import cn.maihe.elg.operation.centers.supports.CenterInterfaceService;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeClaimSettlementResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.GuaranteeRevokeResultBo;
import cn.maihe.elg.operation.centers.supports.model.bo.InnerUploadBaohanFileBo;
import cn.maihe.elg.operation.centers.supports.model.bo.PushCenterGuaranteeBo;
import cn.maihe.elg.operation.config.ZtAccountInfo;
import cn.maihe.elg.operation.exception.CenterException;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.RefundOrderStatus;
import cn.maihe.elg.operation.repository.entity.*;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.guarantee.GuaranteeService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.NoticeRetryInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderInfoService;
import cn.maihe.elg.operation.service.system.impl.OrganizationServiceImpl;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

/**
 * @Description 南平(新点)公共资源服务中心接口服务实现
 * @Author WJH
 * @Date 2021/05/26
 */
@Service
@Slf4j
public abstract class BaseEpointCenterInterfaceService implements CenterInterfaceService {

    @Resource
    private NPEpointBaohanNoticeChannelService npEpointBaohanNoticeChannelService;
    @Resource
    private NPEpointGuarantorRevokeChannelService npEpointGuarantorRevokeChannelService;
    @Resource
    private NPEpointGuarantorClaimSettlementChannelService npEpointGuarantorClaimSettlementChannelService;
    @Resource
    private NPEpointDownloadPublickeyChannelService downloadPublickeyChannelService;
    @Resource
    private NPEpointUploadBaohanFileChannelService uploadBaohanFileChannelService;
    @Resource
    private NPEpointBaohanFileCompleteNoticeChannelService baohanFileCompleteNoticeChannelService;
    @Resource
    private RefundOrderInfoService refundOrderInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private InstitutionService institutionService;
    @Resource
    private ZtAccountInfo ztAccountInfo;
    @Resource
    private OrganizationServiceImpl organizationService;
    @Resource
    private NoticeRetryInfoService noticeRetryInfoService;
    @Resource
    private GuaranteeService guaranteeService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;


    @Override
    public InnerBaseResp<String> pushGuarantee(PushCenterGuaranteeBo bo) {
        GuaranteeVo vo = bo.getGuaranteeVo();
        String applyStatus = bo.getApplyStatus();
        EpointBaohanNoticeReqDTO reqDTO = new EpointBaohanNoticeReqDTO();
        reqDTO.setApplyno(vo.getCenterOrderId());
        reqDTO.setInstname(vo.getGuarantorName());
        reqDTO.setBaohanno(vo.getGuaranteeNo());
        if (vo.getGuaranteeTime() == null) {
            vo.setGuaranteeTime(new Date());
        }
        reqDTO.setGeneratetime(DateUtil.formateDate(vo.getGuaranteeTime(), "yyyy-MM-dd HH:mm:ss"));
//        reqDTO.setGeneratetime(vo.getGuaranteeTime() != null ? DateUtil.formateDate(vo.getGuaranteeTime(), "yyyy-MM-dd HH:mm:ss") : null);
        reqDTO.setApplystatus(applyStatus);
        if (!getCenterNoEnum().equals(CenterNoEnum.PUTIAN)) {
            reqDTO.setCost(fen2yuanString(Long.valueOf(vo.getAmount())));
        }
        //0.01% 转0.0001
        //reqDTO.setRate(getPercentageToDecimal(vo.getRate()));
        InnerBaseResp<String> innerBaseResp = null;

        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(vo.getAcceptOrderNo());
        Assert.notNull(acceptOrderInfo, "查无此受理订单记录");
        try {
            EpointBaseRespDTO resp = npEpointBaohanNoticeChannelService.doRequest(getCenterNoEnum(), reqDTO);
            if (EpointRespCodeEnum.isSuccess(resp.getCode())) {
                innerBaseResp = InnerBaseResp.success(reqDTO.getBaohanno());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMessage());
            }
        } catch (Exception e) {
            log.error("开函结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }

        return innerBaseResp;
    }


    protected String fen2yuanString(Long fen) {
        try {
            return BigDecimal.valueOf(fen).divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP).toString();
        } catch (Exception e) {
            throw CenterException.error("分转元失败", e);
        }
    }

    /**
     * 把百分比数转化成对应的小数
     *
     * @param percentageStr 需要转化的百分比字符串
     * @return 转化后的小数
     */
    protected String getPercentageToDecimal(String percentageStr) {
        try {
            if (StringUtil.isBlank(percentageStr)) {
                return new BigDecimal("0.00").toString();
            }
            String replace = percentageStr.replace("%", "");
            return new BigDecimal(replace).divide(BigDecimal.valueOf(100L), 6, RoundingMode.HALF_UP).toString();
        } catch (Exception e) {
            throw CenterException.error("百分数转小数失败", e);
        }
    }

    @Override
    public InnerBaseResp noticeGuaranteeRevokeResult(GuaranteeRevokeResultBo bo) {
        EpointGuaranteeRevokeReqDTO reqDTO = new EpointGuaranteeRevokeReqDTO();
        reqDTO.setApplyno(bo.getCenterOrderId());
        reqDTO.setBaohanno(bo.getGuaranteeNo());

        GuaranteeDO guarantee = guaranteeService.getGuaranteeByGuaranteeNo(reqDTO.getBaohanno());
        Assert.notNull(guarantee, "查无此保函记录");

        InnerBaseResp<String> innerBaseResp = null;
        try {
            EpointBaseRespDTO resp = npEpointGuarantorRevokeChannelService.doRequest(getCenterNoEnum(), reqDTO);
            if (EpointRespCodeEnum.isSuccess(resp.getCode())) {
                //保函编号作为序列号
                innerBaseResp = InnerBaseResp.success(reqDTO.getBaohanno());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMessage());
            }
        } catch (Exception e) {
            log.error("保函撤销|退保结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }

    @Override
    public InnerBaseResp noticeGuaranteeClaimSettlementResult(GuaranteeClaimSettlementResultBo bo) {
        EpointGuaranteeClaimSettlementReqDTO reqDTO = new EpointGuaranteeClaimSettlementReqDTO();
        RefundOrderInfoDO refundOrderInfo = bo.getRefundOrderInfo();
        //原理赔申请接口中的 业务流水号
        reqDTO.setApplyno(refundOrderInfo.getRefundOrderNo());
        reqDTO.setBaohanno(refundOrderInfo.getGuaranteeNo());

        ProjectInfoDO projectInfoDO = projectInfoService.selectById(refundOrderInfo.getProjectId());
        //赔付状态，1待赔付2已赔付3不予赔付9其他
        if (refundOrderInfo.getStatus() == RefundOrderStatus.UNREFUND.getStatus() ||
                refundOrderInfo.getStatus() == RefundOrderStatus.APPROVAL.getStatus()
        ) {
            reqDTO.setCompensatestatus("1");
            reqDTO.setCompensateremark(refundOrderInfo.getRemark());
        } else if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUNDED.getStatus()) {
            reqDTO.setCompensatestatus("2");
            reqDTO.setCompensateremark(refundOrderInfo.getRemark());
        } else if (refundOrderInfo.getStatus() == RefundOrderStatus.REFUSED.getStatus()) {
            reqDTO.setCompensatestatus("3");
            reqDTO.setCompensateremark(refundOrderInfo.getRemark());
        } else {
            reqDTO.setCompensatestatus("9");
            reqDTO.setCompensateremark(refundOrderInfo.getRemark());
        }
        OrganizationDO organization = organizationService.getOrganization(refundOrderInfo.getOrgId());

        reqDTO.setCompensatename(ztAccountInfo.getAccName());
        reqDTO.setCompensateorgnum(organization.getCreditCode());
        reqDTO.setCompensatecontact(organization.getContactName());
        reqDTO.setCompensatecontacttel(organization.getContactTel());
        //还是取值 ztAccountInfo FIXME
        reqDTO.setCompensatebankcode(ztAccountInfo.getAccNo());
        reqDTO.setCompensateopenbank(ztAccountInfo.getOpenBankName());

        reqDTO.setFavoreename(projectInfoDO.getTenderer());
        reqDTO.setFavoreeorgnum(projectInfoDO.getTendererCreditCode());
        reqDTO.setFavoreecontact(projectInfoDO.getTendererContact());
        reqDTO.setFavoreecontacttel(projectInfoDO.getTendererContactTel());
        reqDTO.setFavoreebankcode(projectInfoDO.getTendererBankCode());
        reqDTO.setFavoreeopenbank(projectInfoDO.getTendererBankOpenbank());
        Long claimFenAmt = StringUtils.isBlank(refundOrderInfo.getRefundAmount()) ? refundOrderInfo.getBidBond()
                : Long.valueOf(refundOrderInfo.getRefundAmount());
        reqDTO.setCompensateamount(StringUtil.toYuan(claimFenAmt));

        InnerBaseResp<String> innerBaseResp = null;
        try {
            EpointBaseRespDTO resp = npEpointGuarantorClaimSettlementChannelService.doRequest(getCenterNoEnum(), reqDTO);
            if (EpointRespCodeEnum.isSuccess(resp.getCode())) {
                innerBaseResp = InnerBaseResp.success(reqDTO.getBaohanno());
            } else {
                innerBaseResp = InnerBaseResp.error(resp.getMessage());
            }
        } catch (Exception e) {
            log.error("理赔结果通知 >> [{}] 异常:{}", getCenterNoEnum().getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }
        return innerBaseResp;
    }

    @Override
    public InnerBaseResp downloadPublickey(String acceptOrderNo, EpointDownloadPublickeyReqDTO reqDTO) {
        return downloadPublickeyChannelService.downloadPublickey(acceptOrderNo, getCenterNoEnum(), reqDTO);
    }

    @Override
    public InnerBaseResp uploadBaohanFile(String acceptOrderNo, InnerUploadBaohanFileBo bo) {
        return uploadBaohanFileChannelService.uploadBaohanFile(acceptOrderNo, getCenterNoEnum(), bo);
    }

    @Override
    public InnerBaseResp baohanFileCompleteNotice(String acceptOrderNo, EpointBaohanFileCompleteNoticeReqDTO reqDTO) {
        return baohanFileCompleteNoticeChannelService.baohanFileCompleteNotice(acceptOrderNo, getCenterNoEnum(), reqDTO);
    }

}
